
#include <BCharEvent>
#include <BKeyEvent>
#include <BEvent>
#include <BEvent>
#include <BMouseEvent>
#include <BEvent>
#include <BCharEvent>
#include <BDragEvent>
#include <BTextEdit>
#include <BPainter>
#include <BCursor>
#include <BDrag>
#include <BSystem>
#include <BScreen>
#include "member_BWidget.h"
#include "member_BEvent.h"
#include "IWindow.h"
#include "IGlobal.h"

using namespace BWE;

extern BList<IWindowHolder> app_windows;

#ifdef _WIN32

bool IWindow::create()
{
	hwnd = 0;
	hdc = 0;
	context = 0;
	style = WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
	if (boss->frameless())
		style = WS_POPUP | WS_SYSMENU;
	mouseInside = false;

	int  nIconWidth = GetSystemMetrics(SM_CXICON);
	int  nIconHeight = GetSystemMetrics(SM_CYICON);;

	const char* title = boss->title().cstr();

	const BRect& rect = boss->rect();
	int x = rect.x();
	int y = rect.y();
	int w = rect.width();
	int h = rect.height();

	const char* ClassName = "IWindow";

	HINSTANCE hInstance = GetModuleHandle(0);

	WNDCLASSEX wcex;
	memset(&wcex, 0, sizeof(wcex));
	wcex.cbSize = sizeof(wcex);
	wcex.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wcex.lpfnWndProc = WindowProc;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIconA(0, IDI_APPLICATION);
	wcex.hCursor = LoadCursorA(0, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszClassName = ClassName;

	ATOM atom = RegisterClassExA(&wcex);
	
	hwnd = CreateWindowA(ClassName, title, style, x, y, w, h, 0, 0, hInstance, 0);
	if (!hwnd)
	{
		perror("create hwnd failed.");
		return false;
	}

	DragAcceptFiles(hwnd, TRUE);

	//SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
	//BOOL ret0 = SetLayeredWindowAttributes(hwnd, 0, 255, LWA_COLORKEY | LWA_ALPHA);

	hdc = GetDC(hwnd);
	if (!hdc)
	{
		perror("Get hwnd device faild.");
		DestroyWindow(hwnd);
		hwnd = 0;
		return false;
	}

	IWindow* firstWindow = app_windows.first();
	context = CreateContext(hdc);
	if(!context)
	{
		perror("Create GL context faild.");
		DestroyWindow(hwnd);
		hwnd = 0;
		hdc = 0;
		return false;
	}
	if(firstWindow)
	{
		wglShareLists(firstWindow->context, context);
	}
	
	BOOL ret = UpdateWindow(hwnd);

	HIMC himc = ImmGetContext(hwnd);

	return true;
}
bool IWindow::destroy()
{
	if (context)
		wglDeleteContext(context);
	if (hwnd)
		DestroyWindow(hwnd);
	hwnd = 0;
	context = 0;
	return true;
}
bool IWindow::makeCurrent(bool yes)
{
	if (yes)
	{
		if (FALSE == wglMakeCurrent(hdc, context))
		{
			DWORD error = GetLastError();
		}
	}
	else
	{
		if (FALSE == wglMakeCurrent(0, 0))
		{
			DWORD error = GetLastError();
		}
	}
	return true;
}
bool IWindow::swapBuffers()
{
	BOOL ret = SwapBuffers(hdc);
	return ret == TRUE;
}

bool IWindow::setWindowIcon(const BIcon* icon)
{
	//HICON hIcon = (HICON)GetClassLongPtrA(window->hwnd, GCLP_HICON);
	//ICONINFO info = { 0 };
	//if (GetIconInfo(hIcon, &info))
	//{
	//	BITMAP bitmap = { 0 };
	//	if (GetObject(info.hbmColor, sizeof(BITMAP), &bitmap))
	//	{
	//		if (bitmap.bmBitsPixel == 32)
	//		{
	//			LONG size = bitmap.bmWidth * bitmap.bmHeight;
	//			bitmap.bmWidthBytes;
	//			BImage* image = titleIcon->image();
	//			BColor* colors = (BColor*)image->pixels()->data();
	//			::SetBitmapBits(info.hbmColor, size * sizeof(BColor), colors);
	//			::SetClassLongPtrA(window->hwnd, GCLP_HICON, (LONG_PTR)hIcon);
	//		}
	//		DeleteObject(info.hbmColor);
	//		DeleteObject(info.hbmMask);
	//	}
	//}
	return false;
}
void IWindow::setFrameless(bool frameless)
{
	if (frameless)
		::SetWindowLongA(hwnd, GWL_STYLE, WS_OVERLAPPED);
	else
		::SetWindowLongA(hwnd, GWL_STYLE, WS_POPUP);
}

bool IWindow::setWindowTitle(const BString& title)
{
	if (hwnd)
	{
		return TRUE == SetWindowTextA(hwnd, title.cstr());
	}
	return false;
}
BString IWindow::getWindowTitle()
{
	CHAR lpstr[256];
	int len = GetWindowTextA(hwnd, lpstr, 256);
	return lpstr;
}

void IWindow::setWindowPos(const BPoint& pos)
{
	if (hwnd)
	{
		WINDOWINFO winfo;
		::GetWindowInfo(hwnd, &winfo);
		int x = pos.x() - (winfo.rcClient.left - winfo.rcWindow.left);
		int y = pos.y() - (winfo.rcClient.top - winfo.rcWindow.top);
		int width = winfo.rcWindow.right - winfo.rcWindow.left;
		int height = winfo.rcWindow.bottom - winfo.rcWindow.top;
		BOOL ret = MoveWindow(hwnd, x, y, width, height, TRUE);
	}
}
BPoint IWindow::getWindowPos()
{
	if (hwnd)
	{
		RECT windowRect;
		GetWindowRect(hwnd, &windowRect);
		return BPoint(windowRect.left, windowRect.top);
	}
	return boss->pos();
}

void IWindow::setWindowSize(const BSize& size)
{
	if (hwnd)
	{
		WINDOWINFO winfo;
		::GetWindowInfo(hwnd, &winfo);
		int x = winfo.rcWindow.left;
		int y = winfo.rcWindow.top;
		int width = size.width() + (winfo.rcWindow.right - winfo.rcWindow.left) - (winfo.rcClient.right - winfo.rcClient.left);
		int height = size.height() + (winfo.rcWindow.bottom - winfo.rcWindow.top) - (winfo.rcClient.bottom - winfo.rcClient.top);
		BOOL ret = MoveWindow(hwnd, x, y, width, height, TRUE);
	}
}
BSize IWindow::getWindowSize()
{
	if (hwnd)
	{
		RECT centerRect;
		GetClientRect(hwnd, &centerRect);
		int w = centerRect.right - centerRect.left;
		int h = centerRect.bottom - centerRect.top;
		return BSize(w, h);
	}
	return boss->size();
}

bool IWindow::isMaximized()
{
	return TRUE == IsZoomed(hwnd);
}
bool IWindow::isMinimized()
{
	return TRUE == IsIconic(hwnd);
}

void IWindow::showNormal()
{
	if (hwnd)
	{
		ShowWindow(hwnd, SW_SHOWNORMAL);
		shown = true;
	}
}
void IWindow::showMaximized()
{
	if (hwnd)
	{
		ShowWindow(hwnd, SW_SHOWMAXIMIZED);
		shown = true;
	}
}
void IWindow::showMinimized()
{
	if (hwnd)
	{
		ShowWindow(hwnd, SW_SHOWMINIMIZED);
		shown = false;
	}
}
void IWindow::showFullScreen()
{
	if (hwnd)
	{
		ShowWindow(hwnd, SW_SHOWMAXIMIZED);
		shown = true;
	}
}
void IWindow::hideWindow()
{
	if (hwnd)
	{
		ShowWindow(hwnd, SW_HIDE);
		shown = false;
	}
}

void IWindow::freshCursor()
{
	BImage* image = 0;
	CursorType type = Cursor_None;
	if (hoverCursor)
	{
		type = hoverCursor->type();
		image = hoverCursor->image(type);
	}
	if (image)
	{
		while (ShowCursor(FALSE) >= 0)
			ShowCursor(FALSE);
		return;
	}
	while (ShowCursor(TRUE) < 0)
		ShowCursor(TRUE);
	switch (type)
	{
	case Cursor_None:
	case Cursor_Arrow:
		SetCursor(LoadCursor(0, IDC_ARROW));
		break;
	case Cursor_Ibeam:
		SetCursor(LoadCursor(0, IDC_IBEAM));
		break;
	case Cursor_Cross:
		SetCursor(LoadCursor(0, IDC_CROSS));
		break;
	case Cursor_Wait:
		SetCursor(LoadCursor(0, IDC_WAIT));
		break;
	case Cursor_Forbidden:
		SetCursor(LoadCursor(0, IDC_NO));
		break;
	case Cursor_Hand:
		SetCursor(LoadCursor(0, IDC_HAND));
		break;
	case Cursor_Help:
		SetCursor(LoadCursor(0, IDC_HELP));
		break;
	case Cursor_SizeVer:
	case Cursor_SizeTop:
	case Cursor_SizeBottom:
		SetCursor(LoadCursor(0, IDC_SIZENS));
		break;
	case Cursor_SizeHor:
	case Cursor_SizeLeft:
	case Cursor_SizeRight:
		SetCursor(LoadCursor(0, IDC_SIZEWE));
		break;
	case Cursor_SizeLeftTop:
	case Cursor_SizeRightBottom:
		SetCursor(LoadCursor(0, IDC_SIZENWSE));
		break;
	case Cursor_SizeLeftBottom:
	case Cursor_SizeRightTop:
		SetCursor(LoadCursor(0, IDC_SIZENESW));
		break;
	case Cursor_SizeAll:
		SetCursor(LoadCursor(0, IDC_SIZEALL));
		break;
	case Cursor_UpArrow:
		SetCursor(LoadCursor(0, IDC_UPARROW));
		break;
	default:
		break;
	}
}

Button filterButton(UINT message)
{
	switch(message)
	{
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_LBUTTONDBLCLK:
		return Button_Left;
		
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_MBUTTONDBLCLK:
		return Button_Middle;
		
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
	case WM_RBUTTONDBLCLK:
		return Button_Right;
		
	}
	return Button_None;
}

HGLRC BWE::CreateContext(HDC hdc)
{
	PIXELFORMATDESCRIPTOR pixelFormat;
	memset(&pixelFormat, 0, sizeof(pixelFormat));
	pixelFormat.nSize = sizeof(pixelFormat);
	pixelFormat.nVersion = 1;
	pixelFormat.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
	pixelFormat.iPixelType = PFD_TYPE_RGBA;
	pixelFormat.cColorBits = 32;
	pixelFormat.cDepthBits = 32;
	pixelFormat.iLayerType = PFD_MAIN_PLANE;

	int pixelFormatIndex = ChoosePixelFormat(hdc, &pixelFormat);
	if (pixelFormatIndex == 0)
		return 0;

	DescribePixelFormat(hdc, pixelFormatIndex, sizeof(PIXELFORMATDESCRIPTOR), &pixelFormat);

	int result = SetPixelFormat(hdc, pixelFormatIndex, &pixelFormat);
	if (!result)
		return 0;
	
	return wglCreateContext(hdc);
}

LRESULT CALLBACK BWE::WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	if (message == WM_IME_REQUEST)
	{
		int value = 0;
		switch (wparam)
		{
		case IMR_CANDIDATEWINDOW:
			value = 0;
			break;
		case IMR_COMPOSITIONFONT:
			value = 0;
			break;
		case IMR_CONFIRMRECONVERTSTRING:
			value = 0;
			break;
		case IMR_DOCUMENTFEED:
			value = 0;
			break;
		case IMR_QUERYCHARPOSITION:
		{
			IMECHARPOSITION* ptr = (IMECHARPOSITION*)lparam;
			ptr->pt.x = 500;
			ptr->pt.y = 500;
			break;
		}
		case IMR_RECONVERTSTRING:
			value = 0;
			break;
		}
	}
	IWindow* window = 0;
	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* w = app_windows[i];
		if (!w->boss)
			continue;
		if (w->hwnd == hwnd)
		{
			window = w;
			break;
		}
	}
	if (window)
	{
		window->procMessage(message, wparam, lparam);
	}
	if (message == WM_CLOSE)
		return 0;
	return DefWindowProc(hwnd, message, wparam, lparam);
}
bool IWindow::procMessage(UINT message, WPARAM wparam, LPARAM lparam)
{
	switch(message)
	{
	case WM_CREATE:
	{
		refresh = true;
		break;
	}
	case WM_ACTIVATE:
	{
		break;
	}
	case WM_CLOSE:
	{
		BEvent event(Event_Close);
		widget_member(boss)->procEvent(event);
		break;
	}
	case WM_PAINT:
	{
		refresh = true;
		break;
	}
	case WM_SETCURSOR:
	{
		break;
	}
	case WM_TIMER:
	{
		if (wparam)
		{
			KillTimer(hwnd, wparam);
		}
		break;
	}
	case WM_MOVE:
	{
		short x = LOWORD(lparam);
		short y = HIWORD(lparam);
		widget_member(boss)->syncWindowPos(BPoint(x, y));
		break;
	}
	case WM_SIZE:
	{
		int width = LOWORD(lparam);
		int height = HIWORD(lparam);
		widget_member(boss)->syncWindowSize(BSize(width, height));
		break;
	}
	case WM_SETFOCUS:
	{
		focusing = true;
		BEvent focusEvent(Event_Focus);
		focusEvent.setValue(true);
		widget_member(boss)->procEvent(focusEvent);
		break;
	}
	case WM_KILLFOCUS:
	{
		ReleaseCapture();
		focusing = false;
		BEvent focusEvent(Event_Focus);
		focusEvent.setValue(false);
		widget_member(boss)->procEvent(focusEvent);
		keyStates.fill(false);
		break;
	}
	case WM_KEYDOWN:
	{
		Key key = filterKey(wparam);
		keyStates[key] = true;
		if (focusWidget)
		{
			BKeyEvent keyEvent(Event_KeyDown, key);
			event_member(&keyEvent)->window = this;
			widget_member(focusWidget)->procEvent(keyEvent);
		}
		break;
	}
	case WM_KEYUP:
	{
		Key key = filterKey(wparam);
		keyStates[key] = false;
		if (focusWidget)
		{
			BKeyEvent keyEvent(Event_KeyUp, key);
			event_member(&keyEvent)->window = this;
			widget_member(focusWidget)->procEvent(keyEvent);
		}
		break;
	}
	case WM_CHAR:
	{
		if (focusWidget)
		{
			short chr = (short)LOWORD(wparam);
			short flag = (short)LOWORD(lparam);
			if (31 < chr && chr < 127)
			{
				BCode code(chr);
				const char* ustr = code.str();
				BCharEvent charEvent(code);
				event_member(&charEvent)->window = this;
				widget_member(focusWidget)->procEvent(charEvent);
			}
		}
		break;
	}
	case WM_IME_CHAR:
	{
		if (focusWidget)
		{
			short schr = (short)LOWORD(wparam);
			short flag = (short)LOWORD(lparam);
			if (schr < 0)
			{
				BCode code(schr);
				const char* ustr = code.str();
				BCharEvent charEvent(code);
				event_member(&charEvent)->window = this;
				widget_member(focusWidget)->procEvent(charEvent);
			}
		}
		break;
	}
	case WM_LBUTTONDOWN:
	case WM_MBUTTONDOWN:
	case WM_RBUTTONDOWN:
	{
		if (widget_member(boss)->frameless)
			SetCapture(hwnd);
		Button button = filterButton(message);
		BPoint absolutePos((short)LOWORD(lparam), (short)HIWORD(lparam));
		BPoint globalPos = BCursor::GetPos();
		BMouseEvent mouseEvent(Event_MousePress, button);
		event_member(&mouseEvent)->window = this;
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMousePress(mouseEvent);
		break;
	}
	case WM_LBUTTONUP:
	case WM_MBUTTONUP:
	case WM_RBUTTONUP:
	{
		Button button = filterButton(message);
		BPoint absolutePos((short)LOWORD(lparam), (short)HIWORD(lparam));
		BPoint globalPos = BCursor::GetPos();
		BMouseEvent mouseEvent(Event_MouseRelease, button);
		event_member(&mouseEvent)->window = this;
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMouseRelease(mouseEvent);

		break;
	}
	case WM_CAPTURECHANGED:
	{
		break;
	}
	case WM_MOUSEMOVE:
	{
		if (!mouseInside)
		{
			mouseInside = true;
			mouse_pressed = false;
			hoverWidget = boss;
			BMouseEvent mouseEvent(Event_MouseEnter, mouse_button);
			event_member(&mouseEvent)->window = this;
			widget_member(boss)->procEvent(mouseEvent);

			TRACKMOUSEEVENT eventTrack;
			eventTrack.cbSize = sizeof(TRACKMOUSEEVENT);
			eventTrack.dwFlags = TME_LEAVE | TME_HOVER;
			eventTrack.hwndTrack = hwnd;
			eventTrack.dwHoverTime = 0;
			TrackMouseEvent(&eventTrack);
		}
		BPoint absolutePos((short)LOWORD(lparam), (short)HIWORD(lparam));
		BPoint globalPos = BCursor::GetPos();
		BMouseEvent mouseEvent(Event_MouseMove, mouse_button);
		event_member(&mouseEvent)->window = this;
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setGlobalPos(globalPos);
		this->procMouseMove(mouseEvent);

		break;
	}
	case WM_MOUSEHOVER:
	{
		BPoint absolutePos((short)LOWORD(lparam), (short)HIWORD(lparam));
		//printf("mouse hover event : %d\t%d\n", absolutePos.x(), absolutePos.y());
		break;
	}
	case WM_MOUSELEAVE:
	{
		mouseInside = false;
		if (hoverWidget)
		{
			BMouseEvent mouseEvent(Event_MouseLeave, mouse_button);
			event_member(&mouseEvent)->window = this;
			widget_member(hoverWidget)->procEvent(mouseEvent);
			hoverWidget = 0;
		}
		break;
	}
	case WM_MOUSEWHEEL:
	{
		BPoint globalPos((short)LOWORD(lparam), (short)HIWORD(lparam));
		BPoint absolutePos = globalPos - boss->pos();
		int wheel = (short)HIWORD(wparam) / 120;
		
		BMouseEvent mouseEvent(Event_MouseWheel, Button_Middle);
		event_member(&mouseEvent)->window = this;
		mouseEvent.setGlobalPos(globalPos);
		mouseEvent.setAbsolutePos(absolutePos);
		mouseEvent.setWheel(wheel);
		this->procMouseWheel(mouseEvent);
		break;
	}
	case WM_CLIPBOARDUPDATE:
	{
		break;
	}
	case WM_DROPFILES:
	{
		const char fileName[256] = {};
		HDROP hDrop = (HDROP)wparam;
		int count = DragQueryFile(hDrop, -1, 0, 0);
		if (count > 0)
		{
			BDrag* drag = new BDrag();
			BDragEvent dragEvent;
			event_member(&dragEvent)->window = this;
			dragEvent.setType(Event_DragDrop);
			dragEvent.setDrag(drag);
			BString text;
			for (int i = 0; i < count; i++)
			{
				DragQueryFile(hDrop, i, (LPSTR)fileName, 256);
				text += fileName;
				text += ';';
			}
			drag->setText(text);
			widget_member(hoverWidget)->procEvent(dragEvent);
		}
		DragFinish(hDrop);
		break;
	}
	case WM_NCMOUSEMOVE:
	{
		break;
	}
	case WM_WINDOWPOSCHANGING:
	{
		break;
	}
	case WM_WINDOWPOSCHANGED:
	{
		break;
	}
	case WM_ACTIVATEAPP:
	{
		break;
	}
	case WM_IME_NOTIFY:
	{
		int a = 642;
		break;
	}
	case WM_IME_SELECT:
	{
		break;
	}
	case WM_IME_SETCONTEXT:
	{
		BOOL fSet = (BOOL)wparam;
		int iShow = (DWORD)lparam;
		break;
	}
	case WM_INPUTLANGCHANGE:
	{
		break;
	}
	case WM_IME_ENDCOMPOSITION:
	{
		break;
	}
	case WM_NCACTIVATE:
	{
		break;
	}
	case WM_NCHITTEST:
	{
		break;
	}
	case WM_CONTEXTMENU:
	{
		break;
	}
	case WM_SYSKEYDOWN:
	{
		if (wparam == VK_MENU)
		{
			Key key = Key_LAlt;
			keyStates[key] = true;
			if (focusWidget)
			{
				BKeyEvent keyEvent(Event_KeyDown, key);
				event_member(&keyEvent)->window = this;
				widget_member(focusWidget)->procEvent(keyEvent);
			}
			break;
		}
		break;
	}
	case WM_SYSKEYUP:
	{
		if (wparam == VK_MENU)
		{
			Key key = Key_LAlt;
			keyStates[key] = true;
			if (focusWidget)
			{
				BKeyEvent keyEvent(Event_KeyUp, key);
				event_member(&keyEvent)->window = this;
				widget_member(focusWidget)->procEvent(keyEvent);
			}
			break;
		}
		break;
	}
	case WM_SYSCHAR:
	{
		break;
	}
	case WM_SYSDEADCHAR:
	{
		break;
	}
	case WM_UNICHAR:
	{
		break;
	}
	default:
		return false;
	}
	return true;
}
Key IWindow::filterKey(WPARAM wparam)
{
	Key key = Key_None;
	switch (wparam)
	{
	case 0x01:	key = Key_LButton;	break;
	case 0x02:	key = Key_RButton;	break;
	case 0x04:	key = Key_MButton;	break;

	case 0x25:	key = Key_Left;		break;
	case 0x26:	key = Key_Up;		break;
	case 0x27:	key = Key_Right;	break;
	case 0x28:	key = Key_Down;		break;

	case 0x30:	key = Key_0;	break;
	case 0x31:	key = Key_1;	break;
	case 0x32:	key = Key_2;	break;
	case 0x33:	key = Key_3;	break;
	case 0x34:	key = Key_4;	break;
	case 0x35:	key = Key_5;	break;
	case 0x36:	key = Key_6;	break;
	case 0x37:	key = Key_7;	break;
	case 0x38:	key = Key_8;	break;
	case 0x39:	key = Key_9;	break;

	case 0x41:	key = Key_A;	break;
	case 0x42:	key = Key_B;	break;
	case 0x43:	key = Key_C;	break;
	case 0x44:	key = Key_D;	break;
	case 0x45:	key = Key_E;	break;
	case 0x46:	key = Key_F;	break;
	case 0x47:	key = Key_G;	break;
	case 0x48:	key = Key_H;	break;
	case 0x49:	key = Key_I;	break;
	case 0x4A:	key = Key_J;	break;
	case 0x4B:	key = Key_K;	break;
	case 0x4C:	key = Key_L;	break;
	case 0x4D:	key = Key_M;	break;
	case 0x4E:	key = Key_N;	break;
	case 0x4F:	key = Key_O;	break;
	case 0x50:	key = Key_P;	break;
	case 0x51:	key = Key_Q;	break;
	case 0x52:	key = Key_R;	break;
	case 0x53:	key = Key_S;	break;
	case 0x54:	key = Key_T;	break;
	case 0x55:	key = Key_U;	break;
	case 0x56:	key = Key_V;	break;
	case 0x57:	key = Key_W;	break;
	case 0x58:	key = Key_X;	break;
	case 0x59:	key = Key_Y;	break;
	case 0x5A:	key = Key_Z;	break;

	case VK_NUMPAD0:	key = Key_Num0;		break;
	case VK_NUMPAD1:	key = Key_Num1;		break;
	case VK_NUMPAD2:	key = Key_Num2;		break;
	case VK_NUMPAD3:	key = Key_Num3;		break;
	case VK_NUMPAD4:	key = Key_Num4;		break;
	case VK_NUMPAD5:	key = Key_Num5;		break;
	case VK_NUMPAD6:	key = Key_Num6;		break;
	case VK_NUMPAD7:	key = Key_Num7;		break;
	case VK_NUMPAD8:	key = Key_Num8;		break;
	case VK_NUMPAD9:	key = Key_Num9;		break;

	case VK_NUMLOCK:	key = Key_NumLock;	break;
	case VK_MULTIPLY:	key = Key_Multiply;	break;
	case VK_ADD:		key = Key_Add;		break;
	case VK_SUBTRACT:	key = Key_Sub;		break;
	case VK_DIVIDE:		key = Key_Divide;	break;

	case VK_F1:			key = Key_F1;	break;
	case VK_F2:			key = Key_F2;	break;
	case VK_F3:			key = Key_F3;	break;
	case VK_F4:			key = Key_F4;	break;
	case VK_F5:			key = Key_F5;	break;
	case VK_F6:			key = Key_F6;	break;
	case VK_F7:			key = Key_F7;	break;
	case VK_F8:			key = Key_F8;	break;
	case VK_F9:			key = Key_F9;	break;
	case VK_F10:		key = Key_F10;	break;
	case VK_F11:		key = Key_F11;	break;
	case VK_F12:		key = Key_F12;	break;

	case VK_END:		key = Key_End;		break;
	case VK_HOME:		key = Key_Home;		break;

	case VK_TAB:		key = Key_Tab;		break;
	case VK_SPACE:		key = Key_Space;	break;

	case VK_DELETE:		key = Key_Delete;	break;
	case VK_BACK:		key = Key_Back;		break;
	case VK_RETURN:		key = Key_Enter;	break;

	case VK_SHIFT:		key = Key_LShift;	break;
	case VK_LSHIFT:		key = Key_LShift;	break;
	case VK_RSHIFT:		key = Key_RShift;	break;
	case VK_CONTROL:	key = Key_LCtrl;	break;
	case VK_LCONTROL:	key = Key_LCtrl;	break;
	case VK_RCONTROL:	key = Key_RCtrl;	break;
	case VK_MENU:		key = Key_LAlt;		break;
	case VK_LMENU:		key = Key_LAlt;		break;
	case VK_RMENU:		key = Key_RAlt;		break;

	case VK_ESCAPE:		key = Key_Escape;	break;

	default:
		break;
	}
	return key;
}

#endif
